﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;

namespace DBProvider.Providers
{
	public class MaterialProvider : IMaterialProvider
	{
		#region IMaterialProvider Members

		public List<MaterialCategory> GetAllMaterialCategory()
		{
			List<MaterialCategory> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var data = db.MaterialCategories;

					if(data != null)
					{
						result = data.ToList();
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public MaterialCategory CreateMaterialCategory(MaterialCategory theMatCat, out string msg)
		{
			if(theMatCat == null)
			{
				throw new ArgumentNullException();
			}

			msg = string.Empty;
			MaterialCategory result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var isExist = db.MaterialCategories.Count(mc => mc.MaterialCategoryName == theMatCat.MaterialCategoryName) > 0;

					if(isExist)
					{
						msg = "名称已存在";
					}
					else
					{
						db.MaterialCategories.InsertOnSubmit(theMatCat);
						db.SubmitChanges();

						result = db.MaterialCategories.SingleOrDefault(mc => mc.MaterialCategoryName == theMatCat.MaterialCategoryName);
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public bool DeleteMaterialCategory(int theMatCatID)
		{
			if(theMatCatID <= 0)
			{
				throw new ArgumentOutOfRangeException();
			}

			var result = false;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var dbMC = db.MaterialCategories.SingleOrDefault(mc => mc.MaterialCategoryID == theMatCatID);

					if(dbMC != null)
					{
						db.MaterialCategories.DeleteOnSubmit(dbMC);
						db.SubmitChanges();

						result = true;
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public bool UpdateMaterialCategory(MaterialCategory theMatCat)
		{
			if(theMatCat == null || theMatCat.MaterialCategoryID <= 0)
			{
				throw new ArgumentException();
			}

			var result = false;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var dbMC = db.MaterialCategories.SingleOrDefault(mc => mc.MaterialCategoryID == theMatCat.MaterialCategoryID);

					if(dbMC != null)
					{
						dbMC.MaterialCategoryDescription = theMatCat.MaterialCategoryDescription;
						dbMC.MaterialCategoryName = theMatCat.MaterialCategoryName;

						db.SubmitChanges();

						result = true;
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public List<Material> GetAllMaterial(int drugStoreID)
		{
			if(drugStoreID <= 0)
			{
				throw new ArgumentException();
			}

			List<Material> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					result = db.Materials.Where(m => m.DrugStoreID == drugStoreID).OrderByDescending(m => m.MaterialAddTime).ToList();
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public List<Material> GetAllMaterial(int pageIndex, int pageSize, out int totalRecords, int drugStoreID)
		{
			if(drugStoreID <= 0)
			{
				throw new ArgumentException();
			}

			List<Material> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					totalRecords = db.Materials.Where(m => m.DrugStoreID == drugStoreID).Count();

					var data = db.Materials.Where(m => m.DrugStoreID == drugStoreID).OrderByDescending(m => m.MaterialAddTime).Skip(pageIndex * pageSize).Take(pageSize);

					if(data != null)
					{
						result = data.ToList();
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public List<Material> GetMaterialByCategory(int theMatCatID, int drugStoreID)
		{
			if(theMatCatID <= 0 || drugStoreID <= 0)
			{
				throw new ArgumentOutOfRangeException();
			}

			List<Material> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var data = from m in db.Materials
										 where m.MaterialCategoryID == theMatCatID && m.DrugStoreID == drugStoreID
										 orderby m.MaterialAddTime descending
										 select m;

					if(data != null)
					{
						result = data.ToList();
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public List<Material> GetMaterialByCategory(int theMatCatID, int pageIndex, int pageSize, out int totalRecords, int drugStoreID)
		{
			if(theMatCatID <= 0 || drugStoreID <= 0)
			{
				throw new ArgumentOutOfRangeException();
			}

			List<Material> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					totalRecords = db.Materials.Count(m => m.MaterialCategoryID == theMatCatID);

					var data = (from m in db.Materials
											where m.MaterialCategoryID == theMatCatID && m.DrugStoreID == drugStoreID
											orderby m.MaterialAddTime descending
											select m).Skip(pageIndex * pageSize).Take(pageSize);

					if(data != null)
					{
						result = data.ToList();
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public List<Material> GetAllMaterial(int userID, int drugStoreID)
		{
			if(userID <= 0 || drugStoreID <= 0)
			{
				throw new ArgumentException();
			}

			List<Material> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var user = db.Users.SingleOrDefault(u => u.UserID == userID);

					var data = from m in db.Materials
										 where (m.DrugStoreID == user.DrugStoreID) || (m.IsPublic == 1) || ((from ms in db.RLT_MaterialAndShareTos
																																												 where ms.ShareToDrugStoreID == user.DrugStoreID
																																												 select ms.MaterialID).Contains(m.MaterialID)) || ((from ms in db.RLT_MaterialAndShareTos
																																																																						where ms.ShareToMemberID == userID
																																																																						select ms.MaterialID).Contains(m.MaterialID))
										 orderby m.MaterialAddTime descending
										 select m;

					if(data != null)
					{
						result = data.ToList();
					}
					//result = db.Materials.Where(m => m.DrugStoreID == drugStoreID).OrderByDescending(m => m.MaterialAddTime).ToList();
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public List<Material> GetAllMaterial(int userID, int pageIndex, int pageSize, out int totalRecords, int drugStoreID)
		{
			if(userID <= 0 || drugStoreID <= 0)
			{
				throw new ArgumentException();
			}

			List<Material> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var user = db.Users.SingleOrDefault(u => u.UserID == userID);

					totalRecords = (from m in db.Materials
													where (m.DrugStoreID == user.DrugStoreID) || (m.IsPublic == 1) || ((from ms in db.RLT_MaterialAndShareTos
																																															where ms.ShareToDrugStoreID == user.DrugStoreID
																																															select ms.MaterialID).Contains(m.MaterialID)) || ((from ms in db.RLT_MaterialAndShareTos
																																																																								 where ms.ShareToMemberID == userID
																																																																								 select ms.MaterialID).Contains(m.MaterialID))
													select m).Count();

					var data = (from m in db.Materials
											where (m.DrugStoreID == user.DrugStoreID) || (m.IsPublic == 1) || ((from ms in db.RLT_MaterialAndShareTos
																																													where ms.ShareToDrugStoreID == user.DrugStoreID
																																													select ms.MaterialID).Contains(m.MaterialID)) || ((from ms in db.RLT_MaterialAndShareTos
																																																																						 where ms.ShareToMemberID == userID
																																																																						 select ms.MaterialID).Contains(m.MaterialID))
											orderby m.MaterialAddTime descending
											select m).Skip(pageIndex * pageSize).Take(pageSize);

					if(data != null)
					{
						result = data.ToList();
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public List<Material> GetMaterialByCategory(int userID, int theMatCatID, int drugStoreID)
		{
			if(theMatCatID <= 0 || drugStoreID <= 0 || userID <= 0)
			{
				throw new ArgumentOutOfRangeException();
			}

			List<Material> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var user = db.Users.SingleOrDefault(u => u.UserID == userID);

					var data = from m in db.Materials
										 where m.MaterialCategoryID == theMatCatID && ((m.IsPublic == 1 && m.UploadUserID != userID) || ((from ms in db.RLT_MaterialAndShareTos
																																																											where ms.ShareToDrugStoreID == user.DrugStoreID
																																																											select ms.MaterialID).Contains(m.MaterialID)) || ((from ms in db.RLT_MaterialAndShareTos
																																																																																				 where ms.ShareToMemberID == userID
																																																																																				 select ms.MaterialID).Contains(m.MaterialID)))
										 orderby m.MaterialAddTime descending
										 select m;

					if(data != null)
					{
						result = data.ToList();
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public List<Material> GetMaterialByCategory(int userID, int theMatCatID, int pageIndex, int pageSize, out int totalRecords, int drugStoreID)
		{
			if(theMatCatID <= 0 || drugStoreID <= 0 || userID <= 0)
			{
				throw new ArgumentOutOfRangeException();
			}

			List<Material> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var user = db.Users.SingleOrDefault(u => u.UserID == userID);

					totalRecords = (from m in db.Materials
													where m.MaterialCategoryID == theMatCatID && (m.DrugStoreID == drugStoreID || (m.IsPublic == 1 && m.UploadUserID != userID) || ((from ms in db.RLT_MaterialAndShareTos
																																																													 where ms.ShareToDrugStoreID == user.DrugStoreID
																																																													 select ms.MaterialID).Contains(m.MaterialID)) || ((from ms in db.RLT_MaterialAndShareTos
																																																																																							where ms.ShareToMemberID == userID
																																																																																							select ms.MaterialID).Contains(m.MaterialID)))
													select m).Count();

					var data = (from m in db.Materials
											where m.MaterialCategoryID == theMatCatID && (m.DrugStoreID == drugStoreID || (m.IsPublic == 1 && m.UploadUserID != userID) || ((from ms in db.RLT_MaterialAndShareTos
																																																											 where ms.ShareToDrugStoreID == user.DrugStoreID
																																																											 select ms.MaterialID).Contains(m.MaterialID)) || ((from ms in db.RLT_MaterialAndShareTos
																																																																																					where ms.ShareToMemberID == userID
																																																																																					select ms.MaterialID).Contains(m.MaterialID)))
											orderby m.MaterialAddTime descending
											select m).Skip(pageIndex * pageSize).Take(pageSize);

					if(data != null)
					{
						result = data.ToList();
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public Material CreateMaterial(Material theNewMat, out string msg)
		{
			if(theNewMat == null)
			{
				throw new ArgumentNullException();
			}

			msg = string.Empty;
			Material result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var isExist = db.Materials.Count(m => m.MaterialName == theNewMat.MaterialName) > 0;

					if(isExist)
					{
						msg = "名称已存在";
					}
					else
					{
						db.Materials.InsertOnSubmit(theNewMat);
						db.SubmitChanges();

						result = db.Materials.SingleOrDefault(m => m.MaterialName == theNewMat.MaterialName);
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public bool DeleteMaterial(int theMatID)
		{
			if(theMatID <= 0)
			{
				throw new ArgumentOutOfRangeException();
			}

			var result = false;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var submit = false;

					var dbRlt_MaterialAndShareTo = db.RLT_MaterialAndShareTos.Where(ms => ms.MaterialID == theMatID);

					if(dbRlt_MaterialAndShareTo != null)
					{
						db.RLT_MaterialAndShareTos.DeleteAllOnSubmit(dbRlt_MaterialAndShareTo);
						submit = true;
					}

					var dbMaterial = db.Materials.SingleOrDefault(m => m.MaterialID == theMatID);

					if(dbMaterial != null)
					{
						db.Materials.DeleteOnSubmit(dbMaterial);

						submit = true;
					}

					if(submit)
					{
						db.SubmitChanges();

						result = true;
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public bool UpdateMaterial(Material theMaterial)
		{
			if(theMaterial == null || theMaterial.MaterialID <= 0)
			{
				throw new ArgumentException();
			}

			var result = false;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var dbMaterial = db.Materials.SingleOrDefault(m => m.MaterialID == theMaterial.MaterialID);

					if(dbMaterial != null)
					{
						dbMaterial.Clone(theMaterial);
						db.SubmitChanges();

						result = true;
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public Material GetMaterial(int theMaterialID)
		{
			if(theMaterialID < 0)
			{
				throw new ArgumentOutOfRangeException();
			}

			Material result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					result = db.Materials.SingleOrDefault(m => m.MaterialID == theMaterialID);
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public List<Material> GetNewMaterials(int count, int drugStoreID)
		{
			if(count <= 0 || drugStoreID <= 0)
			{
				throw new ArgumentOutOfRangeException();
			}

			List<Material> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var data = from m in db.Materials
										 where m.DrugStoreID == drugStoreID
										 orderby m.MaterialAddTime descending
										 select m;

					if(data != null)
					{
						result = data.Take(count).ToList();
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public bool DeleteMaterial(List<int> lstMaterialID)
		{
			if(lstMaterialID == null || lstMaterialID.Count <= 0)
			{
				throw new ArgumentException();
			}

			var result = false;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var submit = false;

					var dbRlt_MaterialAndShareTo = db.RLT_MaterialAndShareTos.Where(ms => lstMaterialID.Contains(ms.MaterialID));

					if(dbRlt_MaterialAndShareTo != null)
					{
						db.RLT_MaterialAndShareTos.DeleteAllOnSubmit(dbRlt_MaterialAndShareTo);
						submit = true;
					}

					var dbMaterial = from m in db.Materials
													 where lstMaterialID.Contains(m.MaterialID)
													 select m;

					if(dbMaterial != null)
					{
						db.Materials.DeleteAllOnSubmit(dbMaterial);
						submit = true;
					}

					if(submit)
					{
						db.SubmitChanges();

						result = true;
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public List<RLT_MaterialAndShareTo> GetMaterialAndShareToByMaterial(int materialID)
		{
			if(materialID <= 0)
			{
				throw new ArgumentOutOfRangeException();
			}

			List<RLT_MaterialAndShareTo> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					DataLoadOptions dlo = new DataLoadOptions();
					dlo.LoadWith<RLT_MaterialAndShareTo>(ms => ms.User);
					db.LoadOptions = dlo;

					var data = from vs in db.RLT_MaterialAndShareTos
										 where vs.MaterialID == materialID
										 select vs;

					if(data != null)
					{
						result = data.ToList();
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		public void CreateMaterialAndShareTo(List<RLT_MaterialAndShareTo> lstMaterialAndShareTo)
		{
			if(lstMaterialAndShareTo == null || lstMaterialAndShareTo.Count <= 0)
			{
				throw new ArgumentOutOfRangeException();
			}

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					db.RLT_MaterialAndShareTos.InsertAllOnSubmit(lstMaterialAndShareTo);
					db.SubmitChanges();
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}
		}

		public void SaveMaterialAndShareTo(int materialID, List<RLT_MaterialAndShareTo> lstMaterialAndShareTo)
		{
			if(materialID <= 0 || lstMaterialAndShareTo == null)
			{
				throw new ArgumentOutOfRangeException();
			}

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var dbMaterialAndShareTo = from vs in db.RLT_MaterialAndShareTos
																		 where vs.MaterialID == materialID
																		 select vs;

					if(dbMaterialAndShareTo != null)
					{
						var lstDBMaterialAndShareTo = dbMaterialAndShareTo.ToList();

						var deleteItems = lstDBMaterialAndShareTo.Except(lstMaterialAndShareTo);

						if(deleteItems != null)
						{
							db.RLT_MaterialAndShareTos.DeleteAllOnSubmit(deleteItems);
						}

						var newItems = lstMaterialAndShareTo.Except(lstDBMaterialAndShareTo);

						if(newItems != null)
						{
							db.RLT_MaterialAndShareTos.InsertAllOnSubmit(newItems);
						}

						db.SubmitChanges();
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}
		}

		public List<Material> GetNewMaterials(int count, int drugStoreID, int userID)
		{
			if(count <= 0 || drugStoreID <= 0 || userID <= 0)
			{
				throw new ArgumentOutOfRangeException();
			}

			List<Material> result = null;

			try
			{
				using(DBHealthCommunityDataContext db = new DBHealthCommunityDataContext())
				{
					var user = db.Users.SingleOrDefault(u => u.UserID == userID);

					var data = from m in db.Materials
										 where ((m.IsPublic == 1 && m.UploadUserID != userID) || m.DrugStoreID == drugStoreID || ((from ms in db.RLT_MaterialAndShareTos
																																																							 where ms.ShareToDrugStoreID == user.DrugStoreID
																																																							 select ms.MaterialID).Contains(m.MaterialID)) || ((from ms in db.RLT_MaterialAndShareTos
																																																																																	where ms.ShareToMemberID == userID
																																																																																	select ms.MaterialID).Contains(m.MaterialID)))
										 orderby m.MaterialAddTime descending
										 select m;

					if(data != null)
					{
						result = data.Take(count).ToList();
					}
				}
			}
			catch(Exception exc)
			{
				throw exc;
			}

			return result;
		}

		#endregion
	}
}
